/*
 * Copyright (c) 2017. Tencent BlueKing
 */

package com.tencent.bk.utils.http;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

/**
 * HTTP请求工具,包装了HTTPClient连接池，默认最大并发100条连接，向每个地址最多只能同时并发10条
 * 默认忽略校验Server的SSL证书
 */
public class HttpConPoolUtil {

    private static final Logger log = LoggerFactory.getLogger(HttpConPoolUtil.class);

    private static final String encoding = "UTF-8";

    private final static CloseableHttpClient httpClient;

    static {
        httpClient = HttpClientBuilder.create()
                .setDefaultConnectionConfig(
                        ConnectionConfig.custom()
                                .setBufferSize(102400)
                                .setCharset(Charset.forName("utf-8"))
                                .build())
                .setDefaultRequestConfig(RequestConfig.custom().setSocketTimeout(30000).build())
                .disableAutomaticRetries()
                .setSSLHostnameVerifier((hostname, sslSession) -> true)//忽略服务器的SSL证书
                .setMaxConnPerRoute(10)
                .setMaxConnTotal(100)
                .build();
    }

    /**
     * 提交POST请求，并返回数据，用encoding参数解析
     *
     * @param url         提交的地址
     * @param encoding    字符集，用于解析返回的字符串
     * @param content     提交的内容字符串
     * @param contentType 默认"application/x-www-form-urlencoded"
     * @return 返回字符串
     */
    public static String post(String url, String encoding, String content, String contentType) {
        try {
            byte[] resp = post(url, content.getBytes(encoding), contentType);
            if (null == resp)
                return null;
            return new String(resp, encoding);
        } catch (UnsupportedEncodingException e) {
            log.error("String post(String url, String encoding, String content)", e);
            return null;
        }
    }

    /**
     * 提交POST请求，并返回数据，用encoding参数解析
     *
     * @param url
     * @param content
     * @param contentType
     * @return
     */
    public static String post(String url, String content, String contentType) {
        return post(url, encoding, content, contentType);
    }

    /**
     * 提交POST请求，并返回数据（默认采用encoding常量指定的字符集解析）
     *
     * @param url     提交的地址
     * @param content 提交的内容字符串
     * @return 返回字符串
     */
    public static String post(String url, String content) {
        return post(url, encoding, content, "application/x-www-form-urlencoded");
    }

    /**
     * 提交POST请求，并返回字节数组
     *
     * @param url         提交的地址
     * @param content     提交的内容字节数据
     * @param contentType 默认"application/x-www-form-urlencoded"
     * @return 返回字节数组
     */
    public static byte[] post(String url, byte[] content, String contentType) {
        try {
            return post(url, new ByteArrayEntity(content), contentType);
        } catch (Exception e) {
            log.error("byte[] post(String url, byte[] content)", e);
            return null;
        }
    }

    /**
     * 提交POST请求，并返回字节数组
     *
     * @param url           提交的地址
     * @param requestEntity 封装好的请求实体
     * @param contentType   默认"application/x-www-form-urlencoded"
     * @return 返回字节数组
     */
    public static byte[] post(String url, HttpEntity requestEntity, String contentType) throws Exception {
        HttpPost post = new HttpPost(url);
        // 设置为长连接，服务端判断有此参数就不关闭连接。
        post.setHeader("Connection", "Keep-Alive");
        post.setHeader("Content-Type", contentType);
        post.setEntity(requestEntity);
        HttpEntity entity = httpClient.execute(post).getEntity();
        return EntityUtils.toByteArray(entity);
    }

    /**
     * GET请求，并返回字符串
     *
     * @param url 提交的地址
     * @return
     */
    public static String get(String url) {
        try {
            HttpGet get = new HttpGet(url);
            // 设置为长连接，服务端判断有此参数就不关闭连接。
            get.setHeader("Connection", "Keep-Alive");
            HttpEntity entity = httpClient.execute(get).getEntity();
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            log.error("String get(String url)", e);
            return "";
        }
    }
}
